/**
 * 点位调试器
 * showAt():生成并显示点位线框
 * hide():隐藏生成的点位线框
 * deleteAll():删除场景内所有生成的点位线框
 *
 * 使用方法：const pointDebugger = new PointDebugger()
 *           scene.add(pointDebugger.pointGroup)
 *           pointDebugger.showAt('red', position)
 *
 */

import * as THREE from 'three';

type ColorName =
  | 'red'
  | 'green'
  | 'yellow'
  | 'blue'
  | 'orange'
  | 'cyan'
  | 'purple'
  | 'pink';

type ColorNameToValue = {
  [key in ColorName]: number;
};

const colorNameToValue: ColorNameToValue = {
  red: 0xff2020,
  green: 0x40ff40,
  blue: 0x0080ff,
  yellow: 0xf0f000,
  orange: 0xff8000,
  cyan: 0x00ffff,
  purple: 0x8000ff,
  pink: 0xff70b0,
};

const geometry = new THREE.OctahedronGeometry();
const material = new THREE.LineBasicMaterial({
  depthTest: false,
  opacity: 0.5,
  transparent: true,
});

export default class PointDebugger {
  pointGroup = new THREE.Group();
  colorNameToLine!: { [colorName in ColorName]: THREE.Line };

  constructor(radius: number) {
    this.colorNameToLine = {
      red: new THREE.Line(geometry, material.clone()),
      green: new THREE.Line(geometry, material.clone()),
      blue: new THREE.Line(geometry, material.clone()),
      yellow: new THREE.Line(geometry, material.clone()),
      orange: new THREE.Line(geometry, material.clone()),
      cyan: new THREE.Line(geometry, material.clone()),
      purple: new THREE.Line(geometry, material.clone()),
      pink: new THREE.Line(geometry, material.clone()),
    };
    
    for (let _colorName in this.colorNameToLine) {
      const colorName = _colorName as ColorName;
      let colorValue = colorNameToValue[colorName];
      const line = this.colorNameToLine[colorName];
      const material = line.material as THREE.LineBasicMaterial;
      material.color.set(colorValue);
      line.name = colorName;
      line.visible = false;
      line.scale.setScalar(radius);
      this.pointGroup.add(line);
    }
  }

  showAt(colorName: ColorName, position: THREE.Vector3) {
    const line = this.colorNameToLine[colorName];
    line.position.copy(position);
    line.visible = true;
  }

  hide(name: ColorName) {
    this.toggleVisible(name, false);
  }

  show(name: ColorName) {
    this.toggleVisible(name, true);
  }

  toggleVisible(name: ColorName, toShow: boolean) {
    const line = this.colorNameToLine[name];
    if (line) line.visible = toShow;
  }

  hideAll() {
    Object.keys(colorNameToValue).forEach((colorName) => {});
    this.pointGroup.children.forEach((node) => {
      if (node instanceof THREE.Line) {
        node.visible = false;
      }
    });
  }

  showAll() {
    this.pointGroup.children.forEach((node) => {
      if (node instanceof THREE.Line) {
        node.visible = true;
      }
    });
  }

  deleteAll() {
    while (this.pointGroup.children.length > 0) {
      this.pointGroup.remove(this.pointGroup.children[0]);
    }
  }
}
